 /* 
 * File:   cObjectMap.cpp
 * Author: josep
 * 
 * Created on 30 / desembre / 2010, 18:39
 */

#include "cObjectMap.h"
#include "cItem.h"
#include "utility.h"
#include "cAnimatedVisibleItem.h"

#define TYPE_STR "type:"
#define LEN_TYPE_STR strlen(TYPE_STR)
#define TILE_INDEX_STR "tileIndex:"
#define LEN_TILE_INDEX_STR strlen(TILE_INDEX_STR)
#define ID_STR "id:"
#define LEN_ID_STR strlen(ID_STR)
#define VALUE_STR "value:"
#define LEN_VALUE_STR strlen(VALUE_STR)
#define ANIMATED_STR "animated:"
#define LEN_ANIMATED_STR strlen(ANIMATED_STR)

cObjectMap::cObjectMap() {
}

cObjectMap::cObjectMap(const cObjectMap& orig) {
}

cObjectMap::~cObjectMap() {
}

void cObjectMap::InitFromIniFile(const char* pName, cData* Data){
    cTexture * img;
    string imageFile;
    string buffer;
    string  iniFileName;
    if(strstr(pName, ".ini")==NULL){
        iniFileName=concatToString("ss", pName, ".ini");
    }

    ifstream inFileStream(iniFileName.c_str());
    if(!inFileStream.is_open()) {
          throw PECVJ2D_ERROR_FILE_NOT_FOUND;
    }

    while(getline(inFileStream, buffer)) {
        if(buffer[0]=='i' && buffer[1]=='m'){
            setImageFileName(buffer, imageFile);
            if((img = Data->loadImage(imageFile, GL_RGBA))!=NULL){
                cTexturizedObject::Init(img);
            }else{
                throw PECVJ2D_ERROR_IMAGE_FILE_NOT_FOUND;
            }
        }else if(buffer[0]=='w'){
            setDimension(buffer);
        }else if(buffer[0]=='h'){
            setDimension(buffer);
        }else if(buffer[0]=='t' && buffer[1]=='i'){
            setTileSize(buffer);
        }else if(buffer[0]=='d' && buffer[4]=='F'){
            setDataFilename(buffer);
        }else if(buffer[0]=='d' && buffer[4]=='E'){
            setDataExtension(buffer);
        }else if(buffer[0]=='i' && buffer[1]=='t'){
            addItem(buffer, tileSize);
        }
    }
    inFileStream.close();

    cObjectMap::Init();
}


/*
void cObjectMap::Init(cTexture* texture, cCamera* Camera){

}
 */

bool cObjectMap::LoadMap(int level){
    int maxTileX;
    int tileY;
    int tileX;
    int p;
    string file;
    bool res;
    FILE *fd;
    int i,j,px,py;
    char objectId;
    int pot10=0;

    res=true;

    if(level<10){
        file = concatToString("ssiss", fileNameConfig.c_str(), "0", level,
                                            ".", extensionFilenameConfig.c_str());
    }else{
        file = concatToString("siss", fileNameConfig.c_str(), level,
                                            ".", extensionFilenameConfig.c_str());
    }

    fd=fopen(file.c_str(),"r");
    if(fd==NULL) return false;

    for(j=MapHeight-1;j>=0;j--){
        px=0;
        py=(j*tileSize);

        i=0;
        while(i<MapWidth){
                fscanf(fd,"%c",&objectId);
                if(objectId==',' || objectId==';' || objectId=='\n'){
                    if(pot10>0){
                        if(cfgItems.find(pot10)!=cfgItems.end()){

                            if(cfgItems[pot10]->GetObjetctType()==ANIMATED_ITEM_OBJECT_TYPE){
                                /*Crear un cAnimatetdItem*/
                                Items.push_back(
                                      new cAnimatedVisibleItem(((cAnimatedVisibleItem&)
                                                                       (*(cfgItems[pot10])))
                                      )
                                );
                            }else{
                                /*Crear un cItem*/
                                Items.push_back(new cItem(*(cfgItems[pot10])));
                            }

                            Items.back()->SetPosX(px);
                            Items.back()->SetPosY(py);


                        }else{
                            //ERROR
                            
                        }
                    }
                    px+=tileSize;

                    pot10=0;
                    i++;

                }else if(objectId!=' '){
                    pot10*=10;
                    pot10+=objectId-48;
                    //Tiles = 1,2,3,...
                }
      }
#ifdef _WIN32
            fscanf(fd,"%c",&objectId); //pass enter
#else
            fscanf(fd,"%c",&objectId); //pass enter
            if(objectId!='\n'){
                fscanf(fd,"%c",&objectId); //pass enter )
            }
#endif
    }

    glEnd();
    glEndList();

    fclose(fd);

    return res;
}

void cObjectMap::Draw(){
    for(list<cItem*>::iterator it=Items.begin();
                                            it!=Items.end(); it++){
        (*it)->Draw();
    }
}

int cObjectMap::GetTileSize(){
    return tileSize;
}

list<cItem*>* cObjectMap::GetItems() {
    return &Items;
}
int cObjectMap::GetMapHeight(){
    return MapHeight;
}

int cObjectMap::GetMapWidth(){
    return MapWidth;
}

void cObjectMap::Init(){
        LoadMap(1);
}

void cObjectMap::setImageFileName(string iniValueLine, string &file){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    file = iniValueLine.substr(lpos, rpos-lpos);
}

void cObjectMap::setDataFilename(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    fileNameConfig = iniValueLine.substr(lpos, rpos-lpos);
}

void cObjectMap::setDataExtension(string iniValueLine){
    int rpos = iniValueLine.find("\r");
    int lpos = iniValueLine.find(CHAR_EQUAL)+1;
    extensionFilenameConfig = iniValueLine.substr(lpos, rpos-lpos);
}


void cObjectMap::setDimension(string iniValueLine){
    if(iniValueLine[0]=='w'){
        MapWidth=stringToint(iniValueLine.substr(iniValueLine.find(CHAR_EQUAL)+1));
    }else{
        MapHeight=stringToint(iniValueLine.substr(iniValueLine.find(CHAR_EQUAL)+1));
    }
}

void cObjectMap::setTileSize(string iniValueLine){
    tileSize = stringToint(iniValueLine.substr(iniValueLine.find(CHAR_EQUAL)+1));
}

void cObjectMap::addItem(string iniValueLine, int tileSize){
    int posIni, posFin, nTiles;
    int type, tileIndex, id, value;
    list<int> List;


    posIni=iniValueLine.find(TYPE_STR)+LEN_TYPE_STR;
    posFin=iniValueLine.find(CHAR_COMMA, posIni);
    type = stringToint(iniValueLine.substr(posIni, posFin-posIni));
    posIni=iniValueLine.find(TILE_INDEX_STR)+LEN_TILE_INDEX_STR;
    posFin=iniValueLine.find(CHAR_COMMA, posIni);
    tileIndex=stringToint(iniValueLine.substr(posIni, posFin-posIni));
    posIni=iniValueLine.find(ID_STR)+LEN_ID_STR;
    posFin=iniValueLine.find(CHAR_COMMA, posIni);
    id=stringToint(iniValueLine.substr(posIni, posFin-posIni));
    posIni=iniValueLine.find(VALUE_STR)+LEN_VALUE_STR;
    posFin=iniValueLine.find(CHAR_COMMA, posIni);
    value=stringToint(iniValueLine.substr(posIni, posFin-posIni));
    if((posIni=iniValueLine.find(ANIMATED_STR))!=iniValueLine.npos){
        posIni=iniValueLine.find(CHAR_L_PARENTHESIS, posIni)+1;
        for(posFin=iniValueLine.find(":", posIni); posFin!=iniValueLine.npos;
                                        posIni=posFin+1, posFin=iniValueLine.find(":", posIni)){
            value = stringToint(iniValueLine.substr(posIni, posFin-posIni));
            List.push_back(value);
        }
        posFin=iniValueLine.find(CHAR_R_PARENTHESIS, posIni);
        value = stringToint(iniValueLine.substr(posIni, posFin-posIni));
        List.push_back(value);

        cAnimatedVisibleItem *AnItem = new cAnimatedVisibleItem();

        AnItem->SetFrameState(0);
        AnItem->SetFrameSeq(0);
        AnItem->SetNFrameStates(1);
        AnItem->SetFrameRate(20);
        AnItem->SetNTilesHor(this->GetTexture()->GetWidth()/tileSize);
        AnItem->SetNTilesVer(this->GetTexture()->GetHeight()/tileSize);
        AnItem->GetImageSequencesVector()->resize(1);
        (*(AnItem->GetImageSequencesVector()))[0].resize(List.size());
        posIni=0;
        for(list<int>::iterator it=List.begin(); it!=List.end(); it++){
            (*(AnItem->GetImageSequencesVector()))[0][posIni].resize(2);
            int maxTileX = this->GetTexture()->GetWidth()/tileSize;
            int tileY = ((*it)-1)/maxTileX;
            int tileX = ((*it)-1)%maxTileX;
            (*(AnItem->GetImageSequencesVector()))[0][posIni][0]=tileX;
            (*(AnItem->GetImageSequencesVector()))[0][posIni++][1]=tileY;
        }
        cfgItems[tileIndex]= AnItem;
    }else{
        int maxTileX = this->GetTexture()->GetWidth()/tileSize;
        int maxTileY = this->GetTexture()->GetHeight()/tileSize;
        int tileY = (tileIndex-1)/maxTileX;
        int tileX = (tileIndex-1)%maxTileX;
        float ratioX = 1.0/maxTileX;
        float ratioY = 1.0/maxTileY;
        cfgItems[tileIndex]=new cItem();
        cfgItems[tileIndex]->SetTextCoord(0,X, tileX*ratioX);
        cfgItems[tileIndex]->SetTextCoord(0,Y, tileY*ratioY);
        cfgItems[tileIndex]->SetTextCoord(1,X, tileX*ratioX+ratioX);
        cfgItems[tileIndex]->SetTextCoord(1,Y, tileY*ratioY+ratioY);
    }

    cfgItems[tileIndex]->Init(this->GetTexture(), 0, 0, id, value, tileSize, tileSize);
}
